/**
*@description 连接redis的方法，get set
*@author bokolin
*/
const redis = require('redis')
const {REDIS_CONF} = require('../config/config')
//创建客户端
const redisClient = redis.createClient(REDIS_CONF.port,REDIS_CONF.host)
const token_expires_in = 60*60*24;	// 令牌的过期时间设置为24小时
const default_expires_in = REDIS_CONF.expireIn || 1800;	// 普通变量过期时间为30分钟
/**
 * @param {string} key 键
 * @param {string} val 值
 * @param {number} timeout 过期时间 单位s 
 */

/**
 * 
 * @param {string} key 
 */


module.exports = {
    redisClient,
    // 设置存储在给定键中的值
    set:function (key, val, timeout = 60*60){
        if(typeof val == 'object'){
            // 
            val = JSON.stringify(val)
        }
        redisClient.set(key, val)
        redisClient.expire(key,timeout)
    },
    // 获取存储在给定键中的值
    get:function get(key){
        return new Promise((resolve, reject)=>{
            redisClient.get(key,(err,val)=>{
                if(err) {
                    reject(err)
                    return
                }
                if(val ==  null) {
                    resolve(null)
                    return
                }
                try {
                    resolve(
                        JSON.parse(val)
                    )
                } catch (error) {
                    resolve(val)
                }
            })
        })
    },
    // 设置一个key的过期的秒数
	expire: function(key, expiresIn){
		redisClient.expire(key, expiresIn || default_expires_in);
	},
    // 删除一个(或多个)键
	del: function(key){
		redisClient.del(key);
	},
    // 查询一个key是否存在
	exists: function(key){
		return new Promise((resolve, reject) => {
			redisClient.exists(key, function(err, result){
				if (err)
					reject(err);
				else
					resolve(result);
			});
		});
	},
    // 获取指定散列键的值
	hget: function(key, name){
		return new Promise((resolve, reject) => {
			redisClient.hget(key, name, function(err, result){
				if (err)
					reject(err);
				else
					resolve(result);
			});
		});
	},

	// 在散列里面关联起给定的键值对
	hset: function(key, name, value, expiresIn){
		redisClient.hset(key, name, value);
		redisClient.expire(key, expiresIn || default_expires_in);
	},

	// 获取散列包含的键值对
	hgetall: function(key){
		return new Promise((resolve, reject) => {
			redisClient.hgetall(key, function(err, result){
				if (err)
					reject(err);
				else
					resolve(result);
			});
		});
	},

	// 为散列里面的一个或多个键设置值
	hmset: function(key, bean, expiresIn){
		redisClient.hmset(key, bean);
		redisClient.expire(key, expiresIn || default_expires_in);
	},

	///////////////////////////////////////////////////////////////////////////
	// 获取用户 session 值
	getSession: async function(sid, name){
		let key = 'session:' + sid;
		try {
			if (name)
				value = await this.hget(key, name);
			else
				value = await this.hgetall(key);
		} catch (err){
			console.log('[store] get session', err);
		}
		if (value){
			// 延长过期时间
			redisClient.ttl(key, function(err, expiresIn){
				if (!err && expiresIn < default_expires_in)
					redisClient.expire(key, default_expires_in);
			})
		}
		return value;
	},

	// 保存用户 session 值
	setSession: function(sid, name, value, expiresIn){
		let key = 'session:' + sid;
		redisClient.hset(key, name, value, expiresIn);
        // 延长过期时间
		redisClient.ttl(key, function(err, expiresIn){
			if (!err && expiresIn < default_expires_in)
				redisClient.expire(key, default_expires_in);
		})
	},
	// 更改用户 session 值
	upSesstion: function(sid, name, value){
		let key = 'session:' + sid;
		redisClient.hset(key, name, value);
		// 延长过期时间
		redisClient.ttl(key, function(err, expiresIn){
			if (!err && expiresIn < default_expires_in)
				redisClient.expire(key, default_expires_in);
		})
	},
	// 删除用户 session 值
	removeSession: function(sid, name){
		// 返回一个promise对象没必要的，删除用户值只会返回成功信息
		return new Promise((resolve,reject)=>{
			let key = 'session:' + sid;
			if (name){
				redisClient.hdel(key, name);
				resolve('success')
			} else {
				redisClient.del(key);
				resolve('success')
			}
			reject('error')
		})
	},

	// 判断用户 session 是否存在
	existSession: async function(sid){
		let key = 'session:' + sid;
		return await this.exists(key);
	},

	// 验证令牌，获取对应的用户信息
	verifyToken: async function(sid){
		let visitor;
		let text = await this.hget('session:' + sid, 'visitor');
		if (text)
			visitor = JSON.parse(text);
		return visitor;
	},
	
	// 创建访问令牌 {id,audience}
	createToken: async function(visitor, expiresIn){
		if (!expiresIn)
			expiresIn = token_expires_in;	// token 过期时间默认2小时
		let vkey = 'token:' + visitor.id;
		if (visitor.audience)
			vkey += ':' + visitor.audience;
		let sid = await this.get(vkey);
		if (sid){
			// 如果用户的令牌已创建，则直接使用旧令牌，延长过期时间
			this.expire(vkey, expiresIn);
		} else {
			// sid = jpart.random(32, 16);
			// 生成16位随机数字
			sid = Math.random().toString(36).substr(2, 16);

			this.set(vkey, sid, expiresIn);
		}
		this.hset('session:' + sid, 'visitor', JSON.stringify(visitor), expiresIn);
		return sid;
	}
}